/**
 * pdf 预览 打印 下载
 *
 * @author wenchuan.li
 * @date 2019/02/01 17:05
 */
define(['plugins/pdfmake/pdfmake.min'], function (pdfMake, rHTML) {

    var SIZES = {
        '4A0': [4767.87, 6740.79],
        '2A0': [3370.39, 4767.87],
        A0: [2383.94, 3370.39],
        A1: [1683.78, 2383.94],
        A2: [1190.55, 1683.78],
        A3: [841.89, 1190.55],
        A4: [595.28, 841.89],
        A5: [419.53, 595.28],
        A6: [297.64, 419.53],
        A7: [209.76, 297.64],
        A8: [147.40, 209.76],
        A9: [104.88, 147.40],
        A10: [73.70, 104.88],
        B0: [2834.65, 4008.19],
        B1: [2004.09, 2834.65],
        B2: [1417.32, 2004.09],
        B3: [1000.63, 1417.32],
        B4: [708.66, 1000.63],
        B5: [498.90, 708.66],
        B6: [354.33, 498.90],
        B7: [249.45, 354.33],
        B8: [175.75, 249.45],
        B9: [124.72, 175.75],
        B10: [87.87, 124.72],
        C0: [2599.37, 3676.54],
        C1: [1836.85, 2599.37],
        C2: [1298.27, 1836.85],
        C3: [918.43, 1298.27],
        C4: [649.13, 918.43],
        C5: [459.21, 649.13],
        C6: [323.15, 459.21],
        C7: [229.61, 323.15],
        C8: [161.57, 229.61],
        C9: [113.39, 161.57],
        C10: [79.37, 113.39],
        RA0: [2437.80, 3458.27],
        RA1: [1729.13, 2437.80],
        RA2: [1218.90, 1729.13],
        RA3: [864.57, 1218.90],
        RA4: [609.45, 864.57],
        SRA0: [2551.18, 3628.35],
        SRA1: [1814.17, 2551.18],
        SRA2: [1275.59, 1814.17],
        SRA3: [907.09, 1275.59],
        SRA4: [637.80, 907.09],
        EXECUTIVE: [521.86, 756.00],
        FOLIO: [612.00, 936.00],
        LEGAL: [612.00, 1008.00],
        LETTER: [612.00, 792.00],
        TABLOID: [792.00, 1224.00]
    };
    // 系数，定义为像素单位与纸张单位换算基数，这个系数在1:1的情况下成立
    // 比如需要生成的pdf宽度 =400px, 那么 pageSize的width = 400/系数
    var xishu = 1.33349;

    //1毫米 约等于 3.78像素
    //当我们知道需要打印pdf的宽高为毫米时可以乘以3.78得到像素单位大小
    var xishummpx = 3.78;

    //毫米与纸张单位间的系数值， 1毫米=2.83467纸张单位值
    var xishummzz = 2.83467;

    var _window = window;

    function PdfUtil() {
        //[dw、dh], dom的长宽，不一定要和A4纸[595.28, 841.89]匹配
        //pageSize: {width:number,height: number},定义成像素 在入口处转换成纸张单位值
        //dw = (595.28 - 左间距 - 右间距)*xishu*N 、 dh= (841.89- 上间距 - 下间距)*xishu*N
        //option.content=[
        // type:'html',v:'<div>...</div>',dw:100,dh:100
        //]
        this.option = {
            // a string or {width:number,height: number} 定义的宽必须小于高（按纵向打印来定义）
            pageSize: 'A4',
            pageOrientation: 'portrait',
            pageMargins: [0, 0, 0, 0],//定义成像素 在入口处转换成纸张单位值
            content: [],
            pdfName: 'newfile.pdf'
        };
        this.makePageCount = 0;
    }

    PdfUtil.prototype.getCanvas = function (h) {
        if (this.mcanvas) {
            this.mcanvas.getContext("2d").clearRect(0, 0, this.mcanvas.width, this.mcanvas.height);
        } else {
            this.mcanvas = document.createElement('canvas');
            this.mcanvas.width = _window * 2;
            this.mcanvas.height = h * 2;
            this.mcanvas.style.width = _window + 'px';
            this.mcanvas.style.height = h + 'px';
        }
        return this.mcanvas;
    };

    PdfUtil.prototype.htmlToPng = function (_obj) {
        var self = this;
        var dimensions = !isString(this.option.pageSize) ? [this.option.pageSize.width, this.option.pageSize.height] : SIZES[this.option.pageSize.toUpperCase()];
        if (!_obj.dw || !_obj.dh) {
            _obj.dw = dimensions[this.option.pageOrientation === 'portrait' ? 0 : 1];
            _obj.dh = dimensions[this.option.pageOrientation === 'portrait' ? 1 : 0];
        }
        var covImage = function () {
            _obj.v = null;
            _obj.image = self.mcanvas.toDataURL("image/png", 1.0);

            var w_h_ = [dimensions[self.option.pageOrientation === 'portrait' ? 0 : 1] - self.option.pageMargins[0] - self.option.pageMargins[2],
                dimensions[self.option.pageOrientation === 'portrait' ? 1 : 0] - self.option.pageMargins[1] - self.option.pageMargins[3]];
            if (isString(self.option.pageSize)) {
                //计算fit值
                _obj.fit = [w_h_[0], w_h_[1]];
                //_obj.fit[0] = _obj.fit[0] - self.option.pageMargins[0] - self.option.pageMargins[2];
                //_obj.fit[1] = _obj.fit[1] - self.option.pageMargins[1] - self.option.pageMargins[3];
            } else {
                _obj.fit = [w_h_[0], w_h_[1]];
                //_obj.width = w_h_[0];
                //_obj.height = w_h_[1];
            }
            runPdf();
        };
        var _canvas = this.getCanvas(_obj.dw, _obj.dh);
        if (!!window.ActiveXObject || "ActiveXObject" in window) {//IE
            var cxt = _canvas.getContext("2d");//然后将画布缩放，将图像放大两倍画到画布上
            cxt.scale(2, 2);
            browser.calculateDocumentContentSize(browser.parseHTML(_obj.v).body, {}, function (el) {
                html2canvas(el, {
                    canvas: _canvas,
                    taintTest: false,
                    //logging: true,
                    onrendered: function (canvas) {//返回的canvas有问题
                        covImage();
                    }
                });
            });
        } else {

            rHTML.drawHTML(_obj.v, _canvas, {
                width: _obj.dw * 2,
                height: _obj.dh * 2,
                zoom: 2 //对dom放大2倍操作
            }).then(function (r) {
                covImage();
            }, function (e) {
                console.log('error, rHTML');
            });
        }
    };

    //不同的pdf生成一个需要先reset
    PdfUtil.prototype.reset = function () {
        _window.pdfUtil = new PdfUtil();
    };

    PdfUtil.prototype.download = function (_option) {
        var option = this.option;
        this.makePageCount = 0;
        for (var f in _option) {
            option[f] = _option[f];
        }
        if (!Array.isArray(this.option.pageMargins)) {
            option.pageMargins = [0, 0, 0, 0];
        } else {
            option.pageMargins = [
                option.pageMargins[0] || 0,
                option.pageMargins[1] || 0,
                option.pageMargins[2] || option.pageMargins[0] || 0,
                option.pageMargins[3] || option.pageMargins[1] || 0];
        }
        option.pageMargins[0] = ofXishufoFixed2(option.pageMargins[0]);
        option.pageMargins[1] = ofXishufoFixed2(option.pageMargins[1]);
        option.pageMargins[2] = ofXishufoFixed2(option.pageMargins[2]);
        option.pageMargins[3] = ofXishufoFixed2(option.pageMargins[3]);
        if (!isString(this.option.pageSize)) {
            option.pageSize.width = ofXishufoFixed2(option.pageSize.width);
            option.pageSize.height = ofXishufoFixed2(option.pageSize.height);
        }
        runPdf();
    };

    function isString(str) {
        return (typeof str == 'string') && str.constructor == String;
    }

    function ofXishufoFixed2(v) {
        return parseFloat((v / xishu).toFixed(2));
    }

    function loopPage() {
        if (pdfUtil.option.content.length >= pdfUtil.makePageCount) {
            var v = pdfUtil.option.content[pdfUtil.makePageCount - 1];
            if (v.type == 'html') {
                pdfUtil.htmlToPng(v);
            } else {
                runPdf();
            }
        }
    }

    function runPdf() {
        pdfUtil.makePageCount++;
        if (pdfUtil.makePageCount > pdfUtil.option.content.length) {
            pdfUtil.makePageCount = 0;
            //pdfMake.createPdf(pdfUtil.option).download(pdfUtil.option.pdfName,pdfUtil.option.cb,{
            //    progressCallback:function (v) {
            //        // (renderedItems / totalItems)值，可以乘以100得到当前进度的百分比
            //        // 这个只是加载进度，是异步的，最终完成还是需要pdfUtil.option.cb
            //        //console.log(v+"....");
            //    },
            //    autoPrint:false//自动调用打印,也许iE不支持 没有测试
            //});
            pdfMake.createPdf(pdfUtil.option).open();
            pdfUtil.reset();
        } else {
            loopPage();
        }
    }

    var browser = (function (theWindow) {
        "use strict";
        var module = {};
        var createHiddenElement = function (doc, tagName, width, height) {
            var element = doc.createElement(tagName);
            // 'display: none' doesn't cut it, as browsers seem to be lazy loading CSS
            element.style.visibility = "hidden";
            element.style.width = width + "px";
            element.style.height = height + "px";
            element.style.position = "absolute";
            element.style.top = (-10000 - height) + "px";
            element.style.left = (-10000 - width) + "px";
            // We need to add the element to the document so that its content gets loaded
            doc.getElementsByTagName("body")[0].appendChild(element);
            return element;
        };
        var createHiddenSandboxedIFrame = function (doc, width, height) {
            var iframe = doc.createElement('iframe');
            iframe.style.width = width + "px";
            iframe.style.height = height + "px";
            // 'display: none' doesn't cut it, as browsers seem to be lazy loading content
            iframe.style.visibility = "hidden";
            iframe.style.position = "absolute";
            iframe.style.top = (-10000 - height) + "px";
            iframe.style.left = (-10000 - width) + "px";
            // Don't execute JS, all we need from sandboxing is access to the iframe's document
            iframe.sandbox = 'allow-same-origin';
            // Don't include a scrollbar on Linux
            iframe.scrolling = 'no';
            return iframe;
        };
        var createIframeWithSizeAtZoomLevel1 = function (width, height, zoom) {
            var scaledViewportWidth = Math.floor(width / zoom),
                scaledViewportHeight = Math.floor(height / zoom);
            return createHiddenSandboxedIFrame(theWindow.document, scaledViewportWidth, scaledViewportHeight);
        };

        var calculateZoomedContentSizeAndRoundUp = function (actualViewport, requestedWidth, requestedHeight, zoom) {
            return {
                width: Math.max(actualViewport.width * zoom, requestedWidth),
                height: Math.max(actualViewport.height * zoom, requestedHeight)
            };
        };

        var selectElementOrDescendant = function (element, selector) {
            var descendant = element.querySelector(selector);
            if (descendant) {
                return descendant;
            } else if (element.ownerDocument.querySelector(selector) === element) {
                return element;
            }
            throw {
                message: "Clipping selector not found"
            };
        };

        var elementToFullHtmlDocument = function (element) {
            var tagName = element.tagName.toLowerCase();
            if (tagName === 'html' || tagName === 'body') {
                return element.outerHTML;
            }
            // Simple hack: hide the body from sizing, otherwise browser would apply a 8px margin
            return '<body style="margin: 0;">' + element.outerHTML + '</body>';
        };

        module.parseHtmlFragment = function (htmlFragment) {
            var doc = theWindow.document.implementation.createHTMLDocument('');
            doc.documentElement.innerHTML = htmlFragment;
            var element = doc.querySelector('body').firstChild;
            if (!element) {
                throw "Invalid source";
            }
            return element;
        };

        var addHTMLTagAttributes = function (doc, html) {
            var attributeMatch = /<html((?:\s+[^>]*)?)>/im.exec(html),
                helperDoc = theWindow.document.implementation.createHTMLDocument(''),
                htmlTagSubstitute,
                i, elementSubstitute, attribute;

            if (!attributeMatch) {
                console.log(" no attributeMatch");
                return;
            }

            htmlTagSubstitute = '<div' + attributeMatch[1] + '></div>';
            helperDoc.documentElement.innerHTML = htmlTagSubstitute;
            elementSubstitute = helperDoc.querySelector('div');

            for (i = 0; i < elementSubstitute.attributes.length; i++) {
                attribute = elementSubstitute.attributes[i];
                doc.documentElement.setAttribute(attribute.name, attribute.value);
            }
        };

        module.parseHTML = function (html) {
            // We should be using the DOMParser, but it is not supported in older browsers
            var doc = theWindow.document.implementation.createHTMLDocument('');
            doc.documentElement.innerHTML = html;
            addHTMLTagAttributes(doc, html);
            return doc;
        };

        module.calculateDocumentContentSize = function (element, options, cb) {
            var zoom = options.zoom || 1,
                iframe;
            iframe = createIframeWithSizeAtZoomLevel1(options.width, options.height, zoom);

            // We need to add the element to the document so that its content gets loaded
            theWindow.document.getElementsByTagName("body")[0].appendChild(iframe);
            iframe.onload = function () {
                console.log('iframe.onload');
                console.log(iframe.contentDocument.body.firstChild);
                //theWindow.document.getElementsByTagName("body")[0].removeChild(iframe);
                cb && cb(iframe.contentDocument.body.firstChild);
            };

            // srcdoc doesn't work in PhantomJS yet
            iframe.contentDocument.open();
            iframe.contentDocument.write('<!DOCTYPE html>');
            iframe.contentDocument.write(elementToFullHtmlDocument(element));
            iframe.contentDocument.close();

        };

        return module;
    }(_window));

    _window.pdfUtil = new PdfUtil();

});